﻿Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Workflow.ComponentModel

Namespace System.Workflow.ComponentModel.Design
    Friend NotInheritable Class CustomActivityDesignerAdapter
        Implements IDisposable
        ' Methods
        Public Sub New(ByVal serviceProvider As IServiceProvider)
            Me.serviceProvider = serviceProvider
            Dim service As IComponentChangeService = [TryCast](Me.serviceProvider.GetService(GetType(IComponentChangeService)),IComponentChangeService)
            If (Not service Is Nothing) Then
                AddHandler service.ComponentAdding, New ComponentEventHandler(AddressOf Me.OnComponentAdding)
                AddHandler service.ComponentAdded, New ComponentEventHandler(AddressOf Me.OnComponentAdded)
            End If
        End Sub

        Private Shared Sub EnsureDefaultChildHierarchy(ByVal designerHost As IDesignerHost)
            Dim rootComponent As CompositeActivity = [TryCast](designerHost.RootComponent,CompositeActivity)
            If ((Not rootComponent Is Nothing) AndAlso (rootComponent.Activities.Count = 0)) Then
                Dim customAttributes As Object() = rootComponent.GetType.GetCustomAttributes(GetType(ToolboxItemAttribute), False)
                Dim attribute As ToolboxItemAttribute = If(((Not customAttributes Is Nothing) AndAlso (customAttributes.GetLength(0) > 0)), [TryCast](customAttributes(0),ToolboxItemAttribute), Nothing)
                If ((Not attribute Is Nothing) AndAlso (Not attribute.ToolboxItemType Is Nothing)) Then
                    Dim componentArray As IComponent() = [TryCast](Activator.CreateInstance(attribute.ToolboxItemType, New Object() { rootComponent.GetType }),ToolboxItem).CreateComponents
                    Dim activity2 As CompositeActivity = Nothing
                    Dim component As IComponent
                    For Each component In componentArray
                        If (component.GetType Is rootComponent.GetType) Then
                            activity2 = [TryCast](component,CompositeActivity)
                            Exit For
                        End If
                    Next
                    If ((Not activity2 Is Nothing) AndAlso (activity2.Activities.Count > 0)) Then
                        Dim service As IIdentifierCreationService = [TryCast](designerHost.GetService(GetType(IIdentifierCreationService)),IIdentifierCreationService)
                        If (Not service Is Nothing) Then
                            Dim childActivities As Activity() = activity2.Activities.ToArray
                            activity2.Activities.Clear
                            service.EnsureUniqueIdentifiers(rootComponent, childActivities)
                            Dim activity3 As Activity
                            For Each activity3 In childActivities
                                rootComponent.Activities.Add(activity3)
                            Next
                            Dim activity4 As Activity
                            For Each activity4 In childActivities
                                WorkflowDesignerLoader.AddActivityToDesigner(designerHost, activity4)
                            Next
                        End If
                    End If
                End If
            End If
        End Sub

        Private Shared Function GetDesignerAttribute(ByVal component As Object, ByVal designerBaseType As Type) As DesignerAttribute
            Dim attribute As Attribute
            For Each attribute In TypeDescriptor.GetAttributes(component)
                Dim attribute2 As DesignerAttribute = [TryCast](attribute,DesignerAttribute)
                If ((Not attribute2 Is Nothing) AndAlso (attribute2.DesignerBaseTypeName = designerBaseType.AssemblyQualifiedName)) Then
                    Return attribute2
                End If
            Next
            Return Nothing
        End Function

        Private Sub OnComponentAdded(ByVal sender As Object, ByVal eventArgs As ComponentEventArgs)
            Dim service As IDesignerHost = DirectCast(Me.serviceProvider.GetService(GetType(IDesignerHost)), IDesignerHost)
            If (Not service Is Nothing) Then
                If (service.RootComponent Is eventArgs.Component) Then
                    Dim rootComponent As Activity = [TryCast](service.RootComponent,Activity)
                    If (Not rootComponent Is Nothing) Then
                        If (TypeOf rootComponent Is CompositeActivity AndAlso (Me.ensureChildHierarchyHandler Is Nothing)) Then
                            Me.ensureChildHierarchyHandler = New EventHandler(AddressOf Me.OnEnsureChildHierarchy)
                            AddHandler Application.Idle, Me.ensureChildHierarchyHandler
                        End If
                        rootComponent.UserData.Item(UserDataKeys.CustomActivity) = False
                    End If
                ElseIf TypeOf eventArgs.Component Is Activity Then
                    If (TypeOf eventArgs.Component Is CompositeActivity AndAlso Helpers.IsCustomActivity([TryCast](eventArgs.Component,CompositeActivity))) Then
                        [TryCast](eventArgs.Component,Activity).UserData.Item(UserDataKeys.CustomActivity) = True
                    Else
                        [TryCast](eventArgs.Component,Activity).UserData.Item(UserDataKeys.CustomActivity) = False
                    End If
                End If
            End If
        End Sub

        Private Sub OnComponentAdding(ByVal sender As Object, ByVal eventArgs As ComponentEventArgs)
            Dim service As IDesignerHost = DirectCast(Me.serviceProvider.GetService(GetType(IDesignerHost)), IDesignerHost)
            If ((Not service Is Nothing) AndAlso (service.RootComponent Is Nothing)) Then
                Dim component As Activity = [TryCast](eventArgs.Component,Activity)
                If ((Not component Is Nothing) AndAlso (CustomActivityDesignerAdapter.GetDesignerAttribute(component, GetType(IRootDesigner)).DesignerTypeName = GetType(ActivityDesigner).AssemblyQualifiedName)) Then
                    Dim designerAttribute As DesignerAttribute = CustomActivityDesignerAdapter.GetDesignerAttribute(component, GetType(IDesigner))
                    If (Not designerAttribute Is Nothing) Then
                        TypeDescriptor.AddAttributes(component, New Attribute() { New DesignerAttribute(designerAttribute.DesignerTypeName, GetType(IRootDesigner)) })
                    End If
                End If
            End If
        End Sub

        Private Sub OnEnsureChildHierarchy(ByVal sender As Object, ByVal e As EventArgs)
            If (Not Me.ensureChildHierarchyHandler Is Nothing) Then
                RemoveHandler Application.Idle, Me.ensureChildHierarchyHandler
                Me.ensureChildHierarchyHandler = Nothing
                Dim service As IDesignerHost = DirectCast(Me.serviceProvider.GetService(GetType(IDesignerHost)), IDesignerHost)
                If (Not service Is Nothing) Then
                    CustomActivityDesignerAdapter.EnsureDefaultChildHierarchy(service)
                End If
            End If
        End Sub

        Private Sub System.IDisposable.Dispose() Implements IDisposable.Dispose
            If (Not Me.ensureChildHierarchyHandler Is Nothing) Then
                RemoveHandler Application.Idle, Me.ensureChildHierarchyHandler
                Me.ensureChildHierarchyHandler = Nothing
            End If
            Dim service As IComponentChangeService = [TryCast](Me.serviceProvider.GetService(GetType(IComponentChangeService)),IComponentChangeService)
            If (Not service Is Nothing) Then
                RemoveHandler service.ComponentAdding, New ComponentEventHandler(AddressOf Me.OnComponentAdding)
                RemoveHandler service.ComponentAdded, New ComponentEventHandler(AddressOf Me.OnComponentAdded)
            End If
        End Sub


        ' Fields
        Private ensureChildHierarchyHandler As EventHandler
        Private serviceProvider As IServiceProvider
    End Class
End Namespace

